<?php

namespace common\service;


use common\model\EntityModel;
use common\model\ProjectTemplateModel;
use common\model\StepCategoryModel;
use support\SingletonTrait;
use think\module\Module;

class EntityUpstreamService
{
    // 单例工具
    use SingletonTrait;

    /**
     * 查询下游实体列表
     * @param $entityId
     * @param bool $crossShotAsset
     * @return array
     */
    public function getDownstreamEntityList($entityId, $crossShotAsset = true): array
    {
        $entity = model(EntityModel::class)->find($entityId);
        $relatedEntities = [];
        // 特殊处理 镜头属于序列的上游
        if ($entity['module_id'] === Module::$moduleDictData['module_index_by_code']['sequence']['id']) {
            $shotList = model(EntityModel::class)->where(['entity_id' => $entity['id']])->field('id')->select();
            if (!empty($shotList)) {
                $relatedEntities = array_merge($relatedEntities, array_column($shotList, 'id'));
            }
        }
        $targets = TemplateService::getInstance()->getModuleTargets($entity['project_id'], $entity['module_id']);
        if (empty($targets)) {
            return $relatedEntities;
        }
        /**
         * 下游一级环节名称
         */
        $targetStepCategories = model(StepCategoryModel::class)
            ->where(['id' => ['IN', implode(',', $targets)]])
            ->cache(C('database.default_query_cache_time'))
            ->select();
        $entityModule = module_by_id($entity['module_id']);
        $entity['json'] = json_decode($entity['json'], true);
        $moduleCode = $entityModule['code'];
        $filter = '';
        foreach ($targetStepCategories as $sourceStepCategory) {
            $currentModuleId = module_by_code($sourceStepCategory['code'])['id'];
            if ($crossShotAsset === false
                && (in_array($moduleCode, ['asset', 'design', 'level']) && in_array($sourceStepCategory['code'], ['storyboard', 'sequence', 'shot'])
                    || in_array($moduleCode, ['storyboard', 'sequence', 'shot']) && in_array($sourceStepCategory['code'], ['asset', 'design', 'level']))
            ) {
                continue;
            }
            // 查询关联我的资产
            $filter .= " (module_id = {$currentModuleId} AND FIND_IN_SET({$entityId},JSON_UNQUOTE(JSON_EXTRACT(json,'$.{$sourceStepCategory['code']}_{$moduleCode}')))) OR";
        }
        if (!empty($filter)) {
            $filter = rtrim($filter, 'OR');
            $entityList = model(EntityModel::class)->where(['project_id' => $entity['project_id']])->where($filter)->field('id')->select();
            if (!empty($entityList)) {
                $relatedEntities = array_merge($relatedEntities, array_column($entityList, 'id'));
            }
        }
        return $relatedEntities;
    }

    /**
     * 获取上游实体
     * @param $entityList
     * @param $moduleProcess
     * @param $entityDataIds
     */
    public function getUpstreamEntity($entityList, $moduleProcess, &$entityDataIds)
    {
        if (!empty($entityList)) {
            foreach ($entityList as $index => $entityListItem) {
                $entityListItem["json"] = json_decode($entityListItem["json"], true);
                $entityList[$index] = $entityListItem;
                if (!isset($entityDataIds[$entityListItem["id"]])) {
                    $entityDataIds[$entityListItem["id"]] = $entityListItem["id"];
                }
            }

            $currentCode = $moduleProcess["code"];
            $moduleEntityIds = [];
            $currentEntityIds = [];
            if (!empty($moduleProcess["relation"])) {
                foreach ($moduleProcess["relation"] as $moduleProcessItem) {
                    // 目前的关联查询 是这样的 level_design,level_asset
                    $moduleProcessItemCode = $moduleProcessItem["code"];
                    foreach ($entityList as $entityListItem) {
                        if (!empty($entityListItem["json"]) && !empty($entityListItem["json"]["{$currentCode}_{$moduleProcessItemCode}"])) {
                            $relationEntityIds = explode(",", $entityListItem["json"]["{$currentCode}_{$moduleProcessItemCode}"]);
                            foreach ($relationEntityIds as $relationEntityId) {
                                $moduleEntityIds[$moduleProcessItem['id']][$relationEntityId] = $relationEntityId;
                            }
                            $currentEntityIds = array_merge($currentEntityIds, $relationEntityIds);
                        }
                    }
                }

                if (!empty($currentEntityIds)) {
                    $currentEntityList = model(EntityModel::class)->where(["id" => ["IN", $currentEntityIds]])->field("id,json")->select();
                    $currentEntityList = array_column($currentEntityList, null, 'id');
                    foreach ($moduleEntityIds as $relationModuleId => $moduleEntityIdList) {
                        $this->getUpstreamEntity(array_intersect_key($currentEntityList, $moduleEntityIdList), $moduleProcess["relation"][$relationModuleId], $entityDataIds);
                    }
                }
            }
        }
    }

    /**
     * 下游获取上游实体
     * @param $entityList
     * @param $moduleProcess
     * @param $entityDataIds
     */
    public function downGetUpstreamEntity($entityList, &$moduleProcess, &$entityDataIds)
    {
        if (empty($entityList)) {
            return;
        }

        $currentEntityIds = [];
        foreach ($entityList as $entityListItem) {
            $entityDataIds[$entityListItem["id"]] = $entityListItem["id"];
            $currentCode = module_by_id($entityListItem['module_id'])['code'];
            if (empty($entityListItem["json"]) || !isset($moduleProcess[$currentCode])) {
                continue;
            }
            $entityListItem["json"] = json_decode($entityListItem["json"], true);
            // 目前的关联查询 是这样的 level_design,level_asset
            foreach ($moduleProcess[$currentCode] as $downModuleCode => $item) {
                if (!empty($entityListItem["json"]["{$currentCode}_{$downModuleCode}"])) {
                    $currentEntityIds = array_merge($currentEntityIds, explode(",", $entityListItem["json"]["{$currentCode}_{$downModuleCode}"]));
                }
            }
        }
        if (empty($currentEntityIds)) {
            return;
        }

        $currentEntityList = model(EntityModel::class)->where(["id" => ["IN", $currentEntityIds]])->field("id,module_id,json")->select();
        $this->downGetUpstreamEntity($currentEntityList, $moduleProcess, $entityDataIds);
    }
}
